/**
 * @author zhounan 
 * @date 2024年6月5日
 * @version V1.0
 */
package org.zn.etl.jdbc;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import javax.sql.DataSource;

import org.springframework.jdbc.core.JdbcTemplate;
import org.zn.etl.misc.DriverClassType;

import lombok.extern.slf4j.Slf4j;

/**
 * @author zhounan 
 * @date 2024年6月5日
 * @version V1.0
 */
@Slf4j
public abstract class Upsert extends Statment{
	
	protected DataSource ds;
	protected List<Map<String, Object>> valueMaps;
	protected static final String INSERT="INSERT INTO ";	
	
	protected JdbcTemplate template;


	public static Upsert newUpsert(String dbType,DataSource ds) {
		
		Upsert up=null;
		
		if(DriverClassType.pg.getDbType().equals(dbType.toLowerCase())) {
			up=new PGUpsert();
			up.ds=ds;
			up.dbType=dbType;
			up.template=new JdbcTemplate(ds);
			
		}
		return up;
		
	}
	
	public static Upsert newUpsert(String dbType,JdbcTemplate template) {
		
		Upsert up=null;
		
		if(DriverClassType.pg.getDbType().equals(dbType.toLowerCase())) {
			up=new PGUpsert();
			up.template=template;
			up.dbType=dbType;
		}
		return up;
		
	}
	
	
	public Upsert set(String schema,String tableName ,String pk,List<String> columns) {
		this.schema=schema;
		this.tableName=tableName;
		this.columns=columns;
		this.pk=pk;
		return this;
	}
	
	
	protected	abstract String buildSql(); 
	
	public void batchUpdate(List<Map<String, Object>> valueMaps) {
		
		String usSql=buildSql();
		
		List<Object[]> values=valueMaps.stream().map(it->{

			Object[] vs=new Object[columns.size()*2-1];
			int i=0;
			
			int x=0;
			
			for (String col : columns) {
				
				vs[i++]=it.get(col);
				if(!Objects.equals(pk, col)) {
					vs[columns.size()+x]=it.get(col);
					x++;
				}
			}
			return vs;
		}).collect(Collectors.toList());
		
		log.debug("execute upsert sql:{}",usSql);
		
		template.batchUpdate(usSql, values);
		
	} 
	
	
	public void batchUpdate2(List<Object[]> values) {
		
		String usSql=buildSql();
		
		log.debug("execute upsert sql:{}",usSql);

		values=values.stream().map(v  ->   {
			
			Object[] n=new Object[v.length*2-1];
			
			System.arraycopy(v, 0, n, 0, v.length);
			System.arraycopy(v, 1, n, v.length, v.length-1);
			
			return n;
			
		} ).collect(Collectors.toList());
		
		template.batchUpdate(usSql, values);
		
	} 
	
	
	public void batchUpdateDirect(List<Object[]> values) {
		
		String usSql=buildSql();
		log.debug("execute upsert sql:{}",usSql);
		template.batchUpdate(usSql, values);
		
		
	}
	
	public void updateDirect(Object[] value) {
		String usSql=buildSql();
		log.debug("execute upsert sql:{}",usSql);
		template.update(usSql, value);
		
		
	}
	
	
	
}
